#include <iostream>
#include <string>
#include <cstdlib>
#include "xinterpret.h"

using namespace std;

bool get_string_line(string &src, string &line);
// Convenience function for treating a string like a stream when reading
// Takes: two string references, a source string to read from and a destination 
// string to store the read line in.
//
// Returns: EOF? true if the end of the string was found, false if not.
//
// Precondition: src is a non empty string.
// Postcondition: src now contains lines 2 - n of itself rather than lines 1 - n
//                line now contains the line that was removed from src.

class ActionSet {
public:
    ActionSet(); // Fills out an ActionSet structure with default values
    ActionSet(string action_data); // Fills out an ActionSet structure by parsing a .xwii file
    string get_name();

/* These are in public deliberately, access is needed from other functions
   for greatest efficiency */
    string name;
    string a, 
           b, 
           one, 
           two, 
           plus, 
           minus,
           up,
           down,
           left,
           right,
           home,
           flick;
};

class CC_ActionSet {
public:
	CC_ActionSet();
	CC_ActionSet(string action_data);
	
	string a,
		   b,
		   x,
		   y,
		   plus,
		   minus,
		   home,
		   d_up,
		   d_down,
		   d_left,
		   d_right,
		   l_part,
		   r_part,
		   l,
		   r,
		   zl,
		   zr,
		   ls_up,
		   ls_down,
		   ls_left,
		   ls_right,
		   rs_up,
		   rs_down,
		   rs_left,
		   rs_right;
};

class NC_ActionSet {
public:
	NC_ActionSet();
	NC_ActionSet(string action_data);
	
	string c,
		   z,
		   stick_up,
		   stick_down,
		   stick_left,
		   stick_right,
		   flick;
};

class GTR_ActionSet {
public:
	GTR_ActionSet();
	GTR_ActionSet(string action_data);
	string get_name();
	
	string green,
		   red,
		   yellow,
		   blue,
		   orange,
		   strum_up,
		   strum_down,
		   js_up,
		   js_down,
		   js_left,
		   js_right,
		   plus,
		   minus,
		   whammy;
};

enum stateType { RELEASED = 0, PRESSED, NO_CHANGE };

class InputState {
public:
    InputState(); // Fills out an InputState structure with default values
    bool a,
         b,
         one,
         two, // each bool is true if an event (press OR release) needs processing
         plus,
         minus,
         up,
         down,
         left,
         right,
         home,
         flick;

     stateType a_type,
               b_type,
               one_type,
               two_type,
               plus_type,
               minus_type,
               up_type,
               down_type,
               left_type,
               right_type,
               home_type,
               flick_type;
};

/*
For each of the XX_InputState() constructors, the boolean parameter "releaseAll" 
determines the default value for all input.  false is the default, it causes 
no buttons to be pressed or released if the object is simply initialised then 
processed with the corresponding xwii_process_XX_input() function.

However, if releaseAll is set to true, it will cause all possible buttons to 
send a release signal (if the object is just initialised and processed).  This 
is useful killing expansion input events when an expansion is unplugged.
*/

class CC_InputState {
public:
	CC_InputState(bool releaseAll = false);
	bool   a,
		   b,
		   x,
		   y,
		   plus,
		   minus,
		   home,
		   d_up,
		   d_down,
		   d_left,
		   d_right,
		   l_part,
		   r_part,
		   l,
		   r,
		   zl,
		   zr,
		   ls_up,
		   ls_down,
		   ls_left,
		   ls_right,
		   rs_up,
		   rs_down,
		   rs_left,
		   rs_right;
	stateType  a_type,
			   b_type,
		  	   x_type,
		       y_type,
		       plus_type,
		       minus_type,
		       home_type,
		       d_up_type,
    		   d_down_type,
    		   d_left_type,
    		   d_right_type,
    		   l_part_type,
    		   r_part_type,
    		   l_type,
    		   r_type,
	    	   zl_type,
	    	   zr_type,
	    	   ls_up_type,
	    	   ls_down_type,
	    	   ls_left_type,
	    	   ls_right_type,
	    	   rs_up_type,
	    	   rs_down_type,
	    	   rs_left_type,
	    	   rs_right_type;
};

class NC_InputState {
public:
	NC_InputState(bool releaseAll = false);
	bool   c,
	       z,
	       stick_up,
	       stick_down,
	       stick_left,
	       stick_right,
	       flick;
	stateType  c_type,
	           z_type,
	           stick_up_type,
	           stick_down_type,
	           stick_left_type,
	           stick_right_type,
	           flick_type;
};

class GTR_InputState {
public:
	GTR_InputState(bool releaseAll = false);
	  bool green,
		   red,
		   yellow,
		   blue,
		   orange,
		   strum_up,
		   strum_down,
		   js_up,
		   js_down,
		   js_left,
		   js_right,
		   plus,
		   minus,
		   whammy;
 
 stateType green_type,
		   red_type,
		   yellow_type,
		   blue_type,
		   orange_type,
		   strum_up_type,
		   strum_down_type,
		   js_up_type,
		   js_down_type,
		   js_left_type,
		   js_right_type,
		   plus_type,
		   minus_type,
		   whammy_type;
};

void xwii_process_input(InputState &istate, ActionSet &actions);
void xwii_process_CC_input(CC_InputState &istate, CC_ActionSet &actions);
void xwii_process_NC_input(NC_InputState &istate, NC_ActionSet &actions);
void xwii_process_GTR_input(GTR_InputState &istate, GTR_ActionSet &actions);
void execute_action(string event, stateType type); 
